/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.fd.service.impl;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.xy.biz.fd.client.DocumentClient;
import com.xy.biz.fd.client.FolderClient;
import com.xy.biz.fd.client.RepositoryClient;
import com.xy.biz.fd.domain.DocumentPermissions;
import com.xy.biz.fd.domain.bo.*;
import com.xy.biz.fd.domain.converter.DocumentShareConverter;
import com.xy.biz.fd.domain.query.DocumentHistoryQuery;
import com.xy.biz.fd.domain.req.documentShare.GetDocumentShareRequest;
import com.xy.biz.fd.domain.req.documentShare.SaveDocumentShareRequest;
import com.xy.biz.fd.domain.resp.GetDocumentShareResponse;
import com.xy.biz.fd.manager.DocumentLogManager;
import com.xy.biz.fd.manager.DocumentManager;
import com.xy.biz.uc.client.UserClient;
import com.xy.biz.uc.client.UserGroupClient;
import com.xy.biz.uc.domain.dto.UserDTO;
import com.xy.biz.uc.domain.dto.UserGroupDTO;
import com.xy.tool.context.UserContextHolder;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xy.lang.domain.Result;
import com.xy.biz.fd.domain.query.DocumentShareQuery;
import com.xy.biz.fd.service.DocumentShareService;
import com.xy.biz.fd.manager.DocumentShareManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.w3c.dom.Document;

import static java.util.stream.Collectors.toList;

/**
 *
 *
 * @author wcs
 * @date 2021-2-8
 */
@Service
public class DocumentShareServiceImpl implements DocumentShareService, InitializingBean {

    @Autowired
    private DocumentShareManager documentShareManager;

    @Autowired
    private DocumentManager documentManager;

    @Autowired
    private DocumentLogManager documentLogManager;

    @Autowired
    private UserClient userClient;

    @Autowired
    private UserGroupClient userGroupClient;

    @Autowired
    private DocumentClient documentClient;

    @Autowired
    private FolderClient folderClient;

    @Autowired
    private RepositoryClient repositoryClient;

    @Autowired
    private DocumentEventBus documentEventBus;

    @Transactional
    @Override
    public Result<?> saveDocumentShare(SaveDocumentShareRequest request) {
        DocumentShareQuery query = DocumentShareQuery.builder()
                .shareType(request.getShareType())//分享文件类型
                .shareId(request.getShareId())//分享文件id
                .shareTargetType(request.getShareTargetType())//分享目标类型
                .repositoryId(request.getRepositoryId())
                .shareTargetIdList(request.getShareTargetIdList())//分享目标id
                .createUserId(UserContextHolder.getUserId()).build();//创建人
        //查询之前存在的直接修改其状态为取消
        documentShareManager.cancelExistingShare(query);

        DocumentShareBO documentShareBO = DocumentShareConverter.toBO(request);
        documentShareBO.setCreateUserId(UserContextHolder.getUserId());
        documentShareBO.setCreateTime(LocalDateTime.now());
        documentShareBO.setUpdateTime(LocalDateTime.now());
        documentShareBO.setDeleteFlag(false);
        int affectedRows = documentShareManager.saveDocumentShare(documentShareBO);
        if (affectedRows > 0) {
            if (request.getShareType() == 0) {
                DocumentBO document = documentManager.getDocument(request.getShareId());
                buildDocumentLog(document);
                DocumentLogBO documentLogBO = buildDocumentLog(document);
                documentLogBO.setAccessType(DocumentPermissions.SHARE);
                documentLogManager.saveDocumentLog(documentLogBO);
            }
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> saveAllDocumentShare(Collection<DocumentShareBO> collection) {
        int affectedRows = documentShareManager.saveAllDocumentShare(collection);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> updateDocumentShare(DocumentShareBO documentShareBO) {
        int affectedRows = documentShareManager.updateDocumentShare(documentShareBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> deleteDocumentShare(Long documentShareId) {
        int affectedRows = documentShareManager.deleteDocumentShare(documentShareId);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> relDeleteDocumentShare(Long documentShareId) {
        int affectedRows = documentShareManager.relDeleteDocumentShare(documentShareId);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<GetDocumentShareResponse> getDocumentShare(Long documentShareId) {
        DocumentShareBO documentShare = documentShareManager.getDocumentShare(documentShareId);
        if (documentShare.getStatus() == 2 && documentShare.getDeadline().isAfter(LocalDateTime.now())) {
            return Result.fail(null, "文件分享已过期！");
        }
        return Result.success(DocumentShareConverter.toResponse(documentShare));
    }

    @Override
    public List<DocumentShareBO> listDocumentShareById(Collection<Long> collection) {
        return documentShareManager.listDocumentShareById(collection);
    }

    @Override
    public List<GetDocumentShareResponse> listDocumentShare(DocumentShareQuery query) {
        //设置分享创建人名称
        List<GetDocumentShareResponse> getDocumentShareResponses = DocumentShareConverter.toResponse(documentShareManager.listDocumentShare(query));
        //已过期分享
        List<Long> collect = getDocumentShareResponses.stream().filter(d -> d.getStatus() == 2 && d.getDeadline().isAfter(LocalDateTime.now())).map(GetDocumentShareResponse::getDocumentShareId).collect(Collectors.toList());
        //求差集
        //List<Long> collect1 = getDocumentShareResponses.stream().filter(item -> !collect.contains(item)).map(GetDocumentShareResponse::getDocumentShareId).collect(toList());
        //设置过期
        if (!CollectionUtils.isEmpty(collect)) {
            documentShareManager.updateDocumentShareS(collect);
        }
        userClient.buildByUser(getDocumentShareResponses,
                getDocumentShareResponses.stream().map(GetDocumentShareResponse::getCreateUserId).collect(Collectors.toSet()),
                GetDocumentShareResponse::getCreateUserId,
                (getDocumentShareResponse, userDTO) -> getDocumentShareResponse.setCreateUserName(userDTO.getUserName()));
        //根据分享（文件）Type确定是知识库、文件夹或文档，设置文件名
        documentClient.buildByDocument(getDocumentShareResponses,
                getDocumentShareResponses.stream()
                        .filter(resp -> resp.getShareType() == 0)
                        .map(GetDocumentShareResponse::getShareId).collect(Collectors.toSet()),
                GetDocumentShareResponse::getShareId,
                (resp, documentDTO) -> {
                    resp.setShareFileName(documentDTO.getDocumentName());
                    resp.setShareFileExtension(documentDTO.getFileExtension());
                });

        folderClient.buildByFolder(getDocumentShareResponses,
                getDocumentShareResponses.stream()
                        .filter(resp -> resp.getShareType() == 1)
                        .map(GetDocumentShareResponse::getShareId).collect(Collectors.toSet()),
                GetDocumentShareResponse::getShareId,
                (resp, folderDTO) -> resp.setShareFileName(folderDTO.getFolderName()));

        repositoryClient.buildByRepository(getDocumentShareResponses,
                getDocumentShareResponses.stream()
                        .filter(resp -> resp.getShareType() == 2)
                        .map(GetDocumentShareResponse::getShareId).collect(Collectors.toSet()),
                GetDocumentShareResponse::getShareId,
                (resp, repositoryDTO) -> resp.setShareFileName(repositoryDTO.getRepositoryName()));

        //根据分享目标（人）Type确定是团队或是个人，设置目标名字
        userGroupClient.buildByUserGroup(getDocumentShareResponses,
                getDocumentShareResponses.stream()
                        .filter(resp -> resp.getShareTargetType() == 1)
                        .map(GetDocumentShareResponse::getShareTargetId).collect(Collectors.toSet()),
                GetDocumentShareResponse::getShareTargetId,
                (resp, userGroupDTO) -> resp.setShareTargetName(userGroupDTO.getUserGroupName()));

        userClient.buildByUser(getDocumentShareResponses,
                getDocumentShareResponses.stream().filter(resp -> resp.getShareTargetType() == 0)
                        .map(GetDocumentShareResponse::getShareTargetId)
                        .collect(Collectors.toSet()),
                GetDocumentShareResponse::getShareTargetId,
                (getDocumentShareResponse, userDTO) -> getDocumentShareResponse.setShareTargetName(userDTO.getUserName()));
        return getDocumentShareResponses;
    }

    @Override
    public int countDocumentShare(DocumentShareQuery query) {
        return documentShareManager.countDocumentShare(query);
    }

    private DocumentLogBO buildDocumentLog(DocumentBO documentBO) {
        DocumentLogBO documentLogBO = new DocumentLogBO();
        documentLogBO.setDocumentId(documentBO.getDocumentId());
        documentLogBO.setDocumentName(documentBO.getDocumentName());
        documentLogBO.setCreateTime(LocalDateTime.now());
        documentLogBO.setCreateUserId(UserContextHolder.getUserId());
        documentLogBO.setVersion(documentBO.getVersion());
        documentLogBO.setTenantId(UserContextHolder.getTenantId());
        documentLogBO.setDeleteFlag(false);
        return documentLogBO;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //将文件夹和文件的原删除标识更改
        documentEventBus.addDocumentStatusHandler((documentId) -> {
            List<DocumentShareBO> documentShareBOS = documentShareManager.listDocumentShare(DocumentShareQuery.max().shareType(0).shareId(documentId).build());
            if (CollectionUtils.isEmpty(documentShareBOS)) {
                return;
            }
            Set<Long> ids = documentShareBOS.stream().map(DocumentShareBO::getDocumentShareId).collect(Collectors.toSet());
            if(!CollectionUtils.isEmpty(ids)){
                documentShareManager.deleteDocumentShareS(ids);
            }
        });
        documentEventBus.addFolderStatusHandler((folderId) -> {
            List<DocumentShareBO> documentShareBOS = documentShareManager.listDocumentShare(DocumentShareQuery.max().shareType(1).shareId(folderId).build());
            if (CollectionUtils.isEmpty(documentShareBOS)) {
                return;
            }
            Set<Long> ids = documentShareBOS.stream().map(DocumentShareBO::getDocumentShareId).collect(Collectors.toSet());
            if(!CollectionUtils.isEmpty(ids)){
                documentShareManager.deleteDocumentShareS(ids);
            }
        });
    }
}
